package com.hdwe.tools.pm.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hdwe.tools.pm.domain.PmRequire;
import com.hdwe.tools.pm.domain.bo.PmRequireBo;
import com.hdwe.tools.pm.domain.vo.PmRequireVo;
import com.hdwe.tools.pm.mapper.PmRequireMapper;
import com.hdwe.tools.pm.service.IPmRequireService;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.service.ComboboxService;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.MarkdownUtil;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.WeChatRobot;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.annotation.CacheCombobox;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.hdwe.tools.pm.config.PmConstant.PM_REQUIRE_DETAIL_PATH;

/**
 * 需求Service业务层处理
 *
 * @author Lion Li
 * @date 2024-12-09
 */
@RequiredArgsConstructor
@Service
public class PmRequireServiceImpl implements IPmRequireService {

    private final PmRequireMapper baseMapper;
    private final ComboboxService comboboxService;
    private final DictService dictService;

    /**
     * 查询需求
     *
     * @param id 主键
     * @return 需求
     */
    @Override
    public PmRequireVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询需求列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 需求分页列表
     */
    @Override
    public TableDataInfo<PmRequireVo> queryPageList(PmRequireBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PmRequire> lqw = buildQueryWrapper(bo);
        Page<PmRequireVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的需求列表
     *
     * @param bo 查询条件
     * @return 需求列表
     */
    @Override
    public List<PmRequireVo> queryList(PmRequireBo bo) {
        LambdaQueryWrapper<PmRequire> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PmRequire> buildQueryWrapper(PmRequireBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PmRequire> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), PmRequire::getTitle, bo.getTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getRequireType()), PmRequire::getRequireType, bo.getRequireType());
        lqw.eq(StringUtils.isNotBlank(bo.getPriority()), PmRequire::getPriority, bo.getPriority());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), PmRequire::getContent, bo.getContent());
        lqw.eq(StringUtils.isNotBlank(bo.getFiles()), PmRequire::getFiles, bo.getFiles());
        lqw.like(StringUtils.isNotBlank(bo.getRelatedUsers()), PmRequire::getRelatedUsers, bo.getRelatedUsers());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), PmRequire::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getOwner()), PmRequire::getOwner, bo.getOwner());
        return lqw;
    }

    @Override
    public List<PmRequireVo> queryRequireProgress() {
        LambdaQueryWrapper<PmRequire> lqw = Wrappers.lambdaQuery();
        lqw.eq(PmRequire::getRequireType, "customer")
            .eq(PmRequire::getStatus, "processing");
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 新增需求
     *
     * @param bo 需求
     * @return 是否新增成功
     */
    @CacheCombobox(cacheName = CacheNames.COMBOBOX_REQUIRE, keyField = "id", valueField = "title")
    @Override
    public Boolean insertByBo(PmRequireBo bo) {
        PmRequire add = MapstructUtils.convert(bo, PmRequire.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            sendMsg(bo);
        }
        return flag;
    }

    private void sendMsg(PmRequireBo bo) {
        String titleLink = MarkdownUtil.createLink(bo.getTitle(), PM_REQUIRE_DETAIL_PATH + bo.getId());
        Map<String, String> map = MapUtil.builder("内容", bo.getContent())
                .put("创建人", comboboxService.queryLabel(CacheNames.COMBOBOX_USER, String.valueOf(LoginHelper.getUserId())))
                .put("优先级", dictService.getDictLabel("pm_priorities", bo.getPriority()))
                .put("关联人", comboboxService.queryLabels(CacheNames.COMBOBOX_USER, String.valueOf(bo.getRelatedUsers())))
                .put("创建时间", DateUtil.now()).map();
        WeChatRobot.sendMarkdownMessage("需求", titleLink, map, bo.getRelatedUsers());
    }

    /**
     * 修改需求
     *
     * @param bo 需求
     * @return 是否修改成功
     */
    @CacheCombobox(cacheName = CacheNames.COMBOBOX_REQUIRE, keyField = "id", valueField = "title")
    @Override
    public Boolean updateByBo(PmRequireBo bo) {
        PmRequire update = MapstructUtils.convert(bo, PmRequire.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PmRequire entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * todo 当需求状态为：已关闭 非需求 重复时，计算耗时
     *
     * @param update 更新对象
     */
    private void calculateCostTime(PmRequire update){
        // 1、获取创建时间
        Date createTime = update.getCreateTime();
        // 2、获取需求对应的任务列表
        // 3、任务列表状态都为完成时，获取最晚修改时间
        // 4、当任务列表有未完成的任务时，需求状态不可以设置为已关闭
        // 4、当任务列表为空时，获取当前时间
        Date latestUpdateTime = new Date();
        // 5、计算耗时
        long costTime = latestUpdateTime.getTime() - createTime.getTime();
        update.setCostTime(costTime);
    }

    /**
     * 校验并批量删除需求信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @CacheCombobox(cacheName = CacheNames.COMBOBOX_REQUIRE)
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
